#include "cpu/exec/template-start.h"
#include "memory/tlb.h"

#define instr mov

static void do_execute() {
	OPERAND_W(op_dest, op_src->val);
	print_asm_template2();
}

make_instr_helper(i2r)
make_instr_helper(i2rm)
make_instr_helper(r2rm)
make_instr_helper(rm2r)

make_helper(concat(mov_a2moffs_, SUFFIX)) {
	swaddr_t addr = instr_fetch(eip + 1, 4);
	MEM_W(addr, REG(R_EAX), R_DS);

	print_asm("mov" str(SUFFIX) " %%%s,0x%x", REG_NAME(R_EAX), addr);
	return 5;
}

make_helper(concat(mov_moffs2a_, SUFFIX)) {
	swaddr_t addr = instr_fetch(eip + 1, 4);
	REG(R_EAX) = MEM_R(addr, R_DS);

	print_asm("mov" str(SUFFIX) " 0x%x,%%%s", addr, REG_NAME(R_EAX));
	return 5;
}

#if DATA_BYTE == 4
make_helper(concat(mov_r2cr_, SUFFIX)) {
	uint8_t modrm = instr_fetch(eip + 1, 1);
	uint8_t cr = (modrm >> 3) & 0x7;
	uint8_t reg = modrm & 0x7;
	if (cr == 0) {
		cpu.cr0.val = reg_l(reg);
	} else if (cr == 3) {
		init_tlb();
		cpu.cr3.val = reg_l(reg);
	}
	else {
		assert(0);
	}
	print_asm("mov" str(SUFFIX) " %%%s,%%cr%d", REG_NAME(reg), cr);
	return 2;
}

make_helper(concat(mov_cr2r_, SUFFIX)) {
	uint8_t modrm = instr_fetch(eip + 1, 1);
	uint8_t cr = (modrm >> 3) & 0x7;
	uint8_t reg = modrm & 0x7;
	if (cr == 0) {
		reg_l(reg) = cpu.cr0.val;
	} else if (cr == 3) {
		reg_l(reg) = cpu.cr3.val;
	}
	else {
		assert(0);
	}
	print_asm("mov" str(SUFFIX) " %%cr%d,%%%s", cr, REG_NAME(reg));
	return 2;
}

#endif

#if DATA_BYTE == 2
make_helper(concat(mov_rm2sr_, SUFFIX)) {
	uint8_t modrm = instr_fetch(eip + 1, 1);
	uint8_t sreg = (modrm >> 3) & 0x7;
	uint8_t reg = modrm & 0x7;
	cpu.sreg[sreg].selector = reg_w(reg);
	load_sreg_cache(sreg);
	print_asm("mov" str(SUFFIX) " %%%s,%%sr%d", REG_NAME(reg), sreg);
	return 2;
}
#endif

#include "cpu/exec/template-end.h"
